package com.xf.system.utils.jwt;

import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Objects;

/**
 * @author xiefengf
 */
public class JwtTokenUtils {

    public static final String TOKEN_HEADER = "Authorization";
    public static final String TOKEN_PREFIX = "Bearer ";
    public static final String SECRET = "JwtSecret";
    public static final String ISS = "xf";

    /**
     * 过期时间8小时
     */
    private static final Long EXPIRATION = 60 * 60 * 8L;

    /**
     * 生成token
     * @param user 用户信息
     */
    public static <T> String createToken(T user, Long tokenValidity) {
        // 过期时间
        Date validity = new Date(System.currentTimeMillis() + EXPIRATION * 1000);
        // 用户信息
        String userJson = JSONObject.toJSONString(user);
        return Jwts.builder()
                // 代表这个JWT的主体，即它的所有人
                .setSubject(userJson)
                // 是一个时间戳，代表这个JWT的签发时间；
                .setIssuedAt(new Date())
                .claim("userJson", userJson)
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .setExpiration(validity)
                .setIssuer(ISS)
                .compact();
    }


    /**
     * 解析Token
     */
    public static <T> T parseToken(Class<T> clazz, String token) {
        if (isExpiration(token)) {
            Claims claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
            String audience = claims.getAudience();
            String userJson = claims.get("userJson", String.class);
            return JSONObject.parseObject(userJson, clazz);
        }
        return null;
    }

    /**
     * 是否已过期
     * @param token token字符串
     * @return true 过期 false 未过期
     */
    public static boolean isExpiration(String token) {
        Claims claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token.replace(TOKEN_PREFIX,"")).getBody();
        return claims.getExpiration().before(new Date());
    }

    /**
     * 获取前端请求头中的Token
     * @return token字符串
     */
    public static String getTokenString(){
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        return request.getHeader(TOKEN_HEADER);
    }

}
